//this simple file show you how to read the XSettings properties (http://standards.freedesktop.org/xsettings-spec/xsettings-spec-0.5.html)
package main

import "fmt"
import "github.com/BurntSushi/xgb/xproto"
import "github.com/BurntSushi/xgb"
import "encoding/binary"
import "io"
import "bytes"

func getAtom(X *xgb.Conn, name string) xproto.Atom {
        reply, err := xproto.InternAtom(X, false, uint16(len(name)), name).Reply()
        if err != nil {
                panic("GetAtom " + name + " Failed")
        }
        return reply.Atom
}

func readString(buf io.Reader, order binary.ByteOrder) string {
        var nameLen uint32
        binary.Read(buf, order, &nameLen)
        if nameLen > 1000 {
                fmt.Println("nameLen Toolong", nameLen)
                return ""
        }

        nameBuf := make([]byte, nameLen)
        binary.Read(buf, order, &nameBuf)
        leftPad := 3 - (nameLen+3)%4
        buf.Read(make([]byte, leftPad))
        return string(nameBuf)
}
func readInterger(buf io.Reader, order binary.ByteOrder) uint32 {
        body := uint32(0)
        binary.Read(buf, order, &body)
        fmt.Println("data in readInterger: ", body)
        return body
}
func readColor(buf io.Reader, order binary.ByteOrder) (r uint16, g uint16, b uint16, a uint16) {
        binary.Read(buf, order, &r)
        binary.Read(buf, order, &g)
        binary.Read(buf, order, &b)
        binary.Read(buf, order, &a)
        return
}

func readString2(buf io.Reader, order binary.ByteOrder) string {
        var nameLen uint16
        binary.Read(buf, order, &nameLen)

        nameBuf := make([]byte, nameLen)
        binary.Read(buf, order, &nameBuf)
        leftPad := 3 - (nameLen+3)%4
        buf.Read(make([]byte, leftPad))
        return string(nameBuf)
}

func readHeader(buf io.Reader, order binary.ByteOrder) (byte, string, uint32) {
        var sType byte
        binary.Read(buf, order, &sType)
        buf.Read(make([]byte, 1))

        name := readString2(buf, order)
        lastSerial := readInterger(buf, order)

        return sType, name, lastSerial
}

func main() {
        X, _ := xgb.NewConn()
        s, _ := xproto.GetSelectionOwner(X, getAtom(X, "_XSETTINGS_S0")).Reply()

        reply, err := xproto.GetProperty(X, false, s.Owner, getAtom(X, "_XSETTINGS_SETTINGS"), getAtom(X, "_XSETTINGS_SETTINGS"), 0, 10240).Reply()
        if err != nil {
                panic(err)
        }
        fmt.Println("win id:", s.Owner)
        data := reply.Value[:reply.ValueLen]
        fmt.Println("reply value len: ", reply.ValueLen)

        var byteOrder binary.ByteOrder
        if data[0] == 1 {
                byteOrder = binary.BigEndian
        } else {
                byteOrder = binary.LittleEndian
        }
        buf := bytes.NewReader(data[4:])

        serial := readInterger(buf, byteOrder)
        numSettings := readInterger(buf, byteOrder)

        fmt.Println("serial:", serial, "Num:", numSettings)
        return
        for i := uint32(0); i < numSettings; i++ {
                sType, name, _ := readHeader(buf, byteOrder)
                switch sType {
                case 0:
                        v := readInterger(buf, byteOrder)
                        fmt.Println(name, "=", v)
                case 1:
                        v := readString(buf, byteOrder)
                        fmt.Println(name, "=", v)
                case 2:
                        r, g, b, a := readColor(buf, byteOrder)
                        fmt.Println(name, "=", r, g, b, a)
                }
        }
}
